
package org.sopt.dev.ImgKnight.agent.database;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;

import org.apache.log4j.Logger;

public class SeenImageDAO {

	private Logger exceptionLogger = null;
	
	public static Connection getConnection() {
		try {
			Class.forName("org.sqlite.JDBC");
			return DriverManager.getConnection("jdbc:sqlite:seenimage.db");
		} catch (ClassNotFoundException e) {
		} catch (SQLException e) {
		}
		return null;
	}
	
	public SeenImageDAO(boolean isCleanStart) {
		exceptionLogger = Logger.getLogger("agent.exception");
		
		Connection conn = null;
		Statement stat = null;
		try {
			conn = getConnection();
			if( conn != null ) {
				stat = conn.createStatement();
				if( isCleanStart )
					stat.executeUpdate("drop table if exists seenimage;");
				stat.executeUpdate("create table if not exists seenimage(BaseHashCode int, FpHashCode int);");
			}
		} catch (Exception e) {
			exceptionLogger.error("Unexpected exception: "+e);
		} finally {
			if( stat != null ) try{ stat.close(); } catch(Exception e){}
			if( conn != null ) try{ conn.close(); } catch(Exception e){}
		}
	}
	
	public synchronized List<Long> selectDiffFpHashCode(long baseHashCode, List<Long> fpHashCodes) {
		Connection conn = null;
		PreparedStatement stat = null;
		ResultSet rs = null;
		List<Long> result = new LinkedList<Long>(fpHashCodes);
		try {
			conn = getConnection();
			if( conn != null ) {
				stat = conn.prepareStatement("select FpHashCode from seenimage where BaseHashCode=?;");
				stat.setLong(1, baseHashCode);
				rs = stat.executeQuery();
				while( rs.next() ) {
					Long fpHashCode = new Long(rs.getLong("FpHashCode"));
					if( fpHashCodes.contains(fpHashCode) )
						result.remove(fpHashCode);
				}
			}
		} catch (Exception e) {
			exceptionLogger.error("Unexpected exception: "+e);
		} finally {
			if( rs != null ) try{ rs.close(); } catch(Exception e){}
			if( stat != null ) try{ stat.close(); } catch(Exception e){}
			if( conn != null ) try{ conn.close(); } catch(Exception e){}
		}
		return result;
	}
	
	public synchronized boolean insertFpHashCode(Long baseHashCode, Set<Long> fpHashCodes) {
		Connection conn = null;
		PreparedStatement stat = null;
		try {
			conn = getConnection();
			if( conn != null ) {
				stat = conn.prepareStatement("insert into seenimage values(?,?);");
				for(Long fpHashCode : fpHashCodes) {
					stat.setLong(1, baseHashCode);
					stat.setLong(2, fpHashCode.longValue());
					stat.addBatch();
				}
				conn.setAutoCommit(false);
				stat.executeBatch();
				conn.setAutoCommit(true);
				return true;
			}
		} catch (Exception e) {
			exceptionLogger.error("seenimage flush fail: "+e);
		} finally {
			if( stat != null ) try{ stat.close(); } catch(Exception e){}
			if( conn != null ) try{ conn.close(); } catch(Exception e){}
		}
		return false;
	}
	
	public synchronized int selectSeenImageSize() {
		Connection conn = null;
		PreparedStatement stat = null;
		ResultSet rs = null;
		int size = -1;
		try {
			conn = getConnection();
			if( conn != null ) {
				stat = conn.prepareStatement("select count(*) as size from seenimage;");
				rs = stat.executeQuery();
				if( rs != null ) {
					if( rs.next() )
						size = rs.getInt("size");
				}
			}
		} catch (Exception e) {
			exceptionLogger.error("Unexpected exception: "+e);
		} finally {
			if( rs != null ) try{ rs.close(); } catch(Exception e){}
			if( stat != null ) try{ stat.close(); } catch(Exception e){}
			if( conn != null ) try{ conn.close(); } catch(Exception e){}
		}
		return size;
	}
	
}
